﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data; 
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;

using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Threading;
using MKIB3Game;

namespace GuiConny
{
    /// <summary>
    /// Interaktionslogik für MyMainWindow.xaml
    /// </summary>
    
   [System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "4.0.0.0")]
   public partial class MyMainWindow : Window
    {
        public static int TIME_OUT_CHAT_SEC = 10;
        public static bool AUTO_CHAT_HIDE = true;
        private bool START_UP_MODE;

       MapCanvas mapCanvas;
       private List<Message> chatMessages;  
       Figure myPlayer;
       public Backend backend; // für testzwecke public
       private Point last_Click_Position ;
       private int timeoutchat;
       private double actual_slider_value;
       private MovementEnum[] movementPath = null; 
      

       [System.Diagnostics.DebuggerNonUserCodeAttribute()]
        
       public MyMainWindow()
        {
            START_UP_MODE = true;
            InitializeComponent();
            init();
            START_UP_MODE = false;
        }

       private void init()
        { // all initialisations 
            backend = new Backend(this);
            
            // begin: testmethode to be replaced by information from backend 
           // this.player = Toolbox.generatePlayers(1, 4)[0];
            // end: testmethode to be replaced by information from backend 
            backend.askServer(ServerEnum.ME);
            backend.askServer(ServerEnum.MAP);
            
           Thread hidechatthread = new Thread(hideChat);
           hidechatthread.Start();



            this.mapslider.Minimum = 10;
            this.mapslider.Maximum = 100;
            this.mapslider.Value = MapCanvas.FIELD_SIZE;
            this.mapCanvas = new MapCanvas();
            this.map_cv.Children.Add(mapCanvas);
            this.chatEingabe.Text = "";
            this.update_Chat();
            this.update_OnlineList();
            this.rename_grid.Visibility = System.Windows.Visibility.Collapsed;
            this.game_grid.Visibility = System.Windows.Visibility.Collapsed;
           
            this.Grid0.Focusable = true;
        }

       //-------------------------- SETTER --------------------------------

       
        
       public void setMap(Map map)
        {
            mapCanvas.setMap(map);
            Dispatcher.BeginInvoke(new ThreadStart(() => mapCanvas.InvalidateVisual()));
            Dispatcher.BeginInvoke(new ThreadStart(() => this.mapScroll()));
            
        }

       public void setPlayers(List<Figure> p)
       {
           mapCanvas.setPlayers(p);
           Dispatcher.BeginInvoke(new ThreadStart(() => mapCanvas.InvalidateVisual()));
       }
       public void setMyPlayer(Figure I)
       {
           this.myPlayer = I;
       }

       public void setDragons(List<Figure> d)
       {
           mapCanvas.setDragons(d);
           Dispatcher.BeginInvoke(new ThreadStart(() => mapCanvas.InvalidateVisual()));
       } 

       public void setMessageBuffer(List<Message> messageBuffer)
       {
           this.chatMessages = messageBuffer;
       }
       // begin: tut nicht!!
       private void set_PlayerImage(String source)
       {
           Console.WriteLine("source set");
           BitmapImage image = new BitmapImage();
           image.BeginInit();
           image.UriSource = new Uri("images/player.png", UriKind.Relative);
           image.EndInit();
          // playerImage.Source = image;
       }
       // ende: tut nicht!!

       // ------------------- Fuktions -------------------------------

       public void update_OnlineList()
        {
            this.onlineInfoGrid.ColumnDefinitions.Clear ();
            this.onlineInfoGrid.RowDefinitions.Clear();
            this.onlineInfoGrid.Children.Clear();

            this.onlineInfoGrid.ColumnDefinitions.Add(new ColumnDefinition());
            this.onlineInfoGrid.ColumnDefinitions.Add(new ColumnDefinition());
            this.onlineInfoGrid.RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto });
            
            Label l = new Label();
            l.Content = "Player online:";
            Grid.SetRow(l, 0);
            this.onlineInfoGrid.Children.Add(l);

            if (mapCanvas != null && mapCanvas.players != null)
            {
                for (int i = 0; i < mapCanvas.players.Count; i++)
                {
                    this.onlineInfoGrid.RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto });
                    l = new Label();
                    l.Content ="ID: " + mapCanvas.players[i].getID() + " - " +  mapCanvas.players[i].getDesc();
                    Grid.SetRow(l, i + 1);
                    this.onlineInfoGrid.Children.Add(l);
                }
            }
        }

       public void update_Chat()
       {
           string chatDisplayed = "Willkommen im Chat!\n";
           if (this.chatMessages != null)
           {
               string src;
               int srcid;
               string text;
               foreach (Message m in this.chatMessages)
               {
                   src = m.getSrc();
                   srcid = m.getSrcID();
                   text = m.getTxt();
                   chatDisplayed += "" + src + ": " + text + "\n";
               }
           } 
           this.timeoutchat = TIME_OUT_CHAT_SEC;
           Dispatcher.BeginInvoke(new ThreadStart(() => chatFeld.Text = chatDisplayed));
           Dispatcher.BeginInvoke(new ThreadStart(() => chatFeld.ScrollToEnd()));
       }
        
       public void updateMe()
       {
           if(myPlayer == null)
           {
            this.myPlayer = backend.getMe();
           }
           if (myPlayer != null)
           {
               int points = myPlayer.getPoints();
               string name = myPlayer.getDesc();
               int x = myPlayer.getX();
               int y = myPlayer.getY();
               Console.WriteLine("------------------------------- " + name);
               Dispatcher.BeginInvoke(new ThreadStart(() =>    playerAttribut1.Content = "X-Coord:" + x));
               Dispatcher.BeginInvoke(new ThreadStart(() =>   playerAttribut2.Content = "y-Coord:" + y));
               Dispatcher.BeginInvoke(new ThreadStart(() =>  playerAttribut3.Content = "Name:" + name));
               Dispatcher.BeginInvoke(new ThreadStart(() => playerAttribut4.Content = "Points: " + points));
                
           }
       }
        
      
       // -------------------- Funktions called by Events --------------------------
       
       private void up_Click(object sender, RoutedEventArgs e)
        {
            Console.WriteLine("up");
            backend.move(MovementEnum.UP);
            mapCanvas.InvalidateVisual();
       
        }

       private void down_Click(object sender, RoutedEventArgs e)
        {
            Console.WriteLine("down");
            backend.move(MovementEnum.DOWN);  
        }

       private void right_Click(object sender, RoutedEventArgs e)
        {
            Console.WriteLine("right");
            backend.move(MovementEnum.RIGHT);
        }

       private void left_Click(object sender, RoutedEventArgs e)
        {
            Console.WriteLine("left");
            backend.move(MovementEnum.LEFT);
        }

       private void key_Down(object sender, KeyEventArgs e)
        {


            if (e.OriginalSource.Equals(this.rename))
            {
                if (e.Key == Key.Return)
                {
                    String newname = rename.Text;
                    backend.RenameMe(newname);
                    this.rename.Clear();
                    this.Grid0.Focus();
                    this.rename_grid.Visibility = System.Windows.Visibility.Collapsed;
                }
                return;
            }
            if (e.OriginalSource.Equals(this.skirm_id))
            {
                if (e.Key == Key.Return)
                { 
                    backend.invitePlayerToChallange(ChallengeTypeEnum.SKIRMISH, Convert.ToInt32(skirm_id.Text));
                    this.skirm_id.Clear();
                    this.Grid0.Focus();
                }
                return; 
            }
            if (e.OriginalSource.Equals(this.dragon_id))
            {
                if (e.Key == Key.Return)
                {
                    backend.invitePlayerToChallange(ChallengeTypeEnum.DRAGON, Convert.ToInt32(dragon_id.Text));
                    this.dragon_id.Clear();
                    this.Grid0.Focus();
                }
                return;
            }
            if (e.OriginalSource.Equals(this.staghunt_id))
            {
                if (e.Key == Key.Return)
                { 
                    backend.invitePlayerToChallange(ChallengeTypeEnum.STAGHUNT, Convert.ToInt32(staghunt_id.Text));
                    this.staghunt_id.Clear();
                    this.Grid0.Focus();
                }
                return;
            }

            // wenn tasten gedrückt werden, außer in der Chateingabe
            if (!e.OriginalSource.Equals(this.chatEingabe) && !e.OriginalSource.Equals(this.rename))
            {
                
                Console.WriteLine("------------------------------------key down: " + e.Key);
                switch (e.Key)
                {
                    case Key.W: backend.move(MovementEnum.UP);break;
                    case Key.A: backend.move(MovementEnum.LEFT); break;
                    case Key.S: backend.move(MovementEnum.DOWN); break;
                    case Key.D: backend.move(MovementEnum.RIGHT); break;
                    case Key.Up: backend.move(MovementEnum.UP); mapScroll(); break;
                    case Key.Down: backend.move(MovementEnum.DOWN); mapScroll(); break;
                    case Key.Left: backend.move(MovementEnum.LEFT); mapScroll(); break;
                    case Key.Right: backend.move(MovementEnum.RIGHT); mapScroll(); break;
                    case Key.Return: this.chatEingabe.Visibility = System.Windows.Visibility.Visible; this.chatEingabe.Focus(); this.timeoutchat = TIME_OUT_CHAT_SEC; e.Handled = true; break;
                    case Key.Tab: this.update_OnlineList();  if (this.onlineInfoGrid.Visibility.Equals(System.Windows.Visibility.Visible)) this.onlineInfoGrid.Visibility = System.Windows.Visibility.Collapsed; else this.onlineInfoGrid.Visibility = System.Windows.Visibility.Visible;
                        this.onlineInfoGrid.Focus(); e.Handled = true; break;
                    case Key.Escape: this.rename_grid.Visibility = System.Windows.Visibility.Visible; this.rename.Focus(); e.Handled = true; break;
                    case Key.Space: if (this.game_grid.Visibility.Equals(System.Windows.Visibility.Visible)) this.game_grid.Visibility = System.Windows.Visibility.Collapsed; else this.game_grid.Visibility = System.Windows.Visibility.Visible;
                        this.game_grid.Focus(); e.Handled = true; break;
                    case Key.L: this.findpath(null); break;
                    case Key.J: Pathfinder.getPath(new Point(3, 3), new Point(this.myPlayer.getX(), this.myPlayer.getY()), backend.getMap()); break;
                }
            }
       
        }
       private void key_Up(object sender, KeyEventArgs e)
       { // wenn tasten gedrückt werden, außer in der Chateingabe
           if (!e.OriginalSource.Equals(this.chatEingabe))
           {
              // Console.WriteLine("------------------------------------key up: " + e.Key);
               switch (e.Key)
               {                    
                   //case Key.Tab: this.onlineInfoGrid.Visibility = System.Windows.Visibility.Collapsed; this.onlineInfoGrid.Focus(); e.Handled = true; break;
                   default: break;
               }
           }
       }

      

       private void onlineInfoGrid_KeyDown(object sender, KeyEventArgs e)
       {
           if (e.Key == Key.Tab)
           {
            

               this.chatEingabe.Clear();
               this.Grid0.Focus();
               this.chatEingabe.Visibility = System.Windows.Visibility.Collapsed;
               this.timeoutchat = TIME_OUT_CHAT_SEC;
           }

       }

       private void chatEingabe_KeyDown(object sender, KeyEventArgs e)
       {
            if (e.Key == Key.Return)
            {
                if (!chatEingabe.Text.Equals(""))
                {
                    String message = chatEingabe.Text;
                    Console.WriteLine("You Entered: " + message);
               
                    if(message.StartsWith("/")){
                       message =  message.TrimStart('/');
                        Console.WriteLine(message);
                        backend.sendServerMessage(message);
                    }
                    else
                        backend.sendMessage(message);
                }
                
                this.chatEingabe.Clear();               
                this.Grid0.Focus();
                this.chatEingabe.Visibility = System.Windows.Visibility.Collapsed;
                this.timeoutchat = TIME_OUT_CHAT_SEC;
            }

       }
       
       private void map_MouseUp(object sender, MouseButtonEventArgs e)
        {
            Console.WriteLine("mouse up event: "  + e.ChangedButton  +" "+ e.GetPosition(this.mapCanvas));
            this.last_Click_Position = e.GetPosition(this.mapCanvas);
           
           Point feld = new Point((int)(this.last_Click_Position.X / MapCanvas.FIELD_SIZE), (int)(this.last_Click_Position.Y / MapCanvas.FIELD_SIZE));
            
           Console.WriteLine("Klick in Feld: "+ feld); 

           this.findpath(Pathfinder.getPath(feld, new Point(this.myPlayer.getX(), this.myPlayer.getY()), backend.getMap()));

        if (!mapCanvas.selection.Remove(feld))
           // mapCanvas.selection.Add(feld);
            mapCanvas.InvalidateVisual();
        }

       private void slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            Console.WriteLine("slider  " + e.NewValue + "old " + e.OldValue+" ");
            this.actual_slider_value = e.NewValue;
        }
 
       private void slider_DragCompleted(object sender, System.Windows.Controls.Primitives.DragCompletedEventArgs e)
        {
            Console.WriteLine("drag Completed"  );
            MapCanvas.FIELD_SIZE = (int)this.actual_slider_value;
            mapCanvas.InvalidateVisual();

        }

       private void scroll_Chached(object sender, ScrollChangedEventArgs e)
       {
           Console.WriteLine("scroll changed" + e.ExtentHeight + " " + e.ExtentWidth + " " + map.HorizontalOffset + " " + map.VerticalOffset + " " + e.HorizontalChange);
            Console.WriteLine(map.ViewportHeight + " " + map.ScrollableHeight);
            Console.WriteLine(map.ViewportWidth + " "+ map.ScrollableWidth);
          
       }

       private void slider_MouseWheel(object sender, MouseWheelEventArgs e)
        {
            Console.WriteLine("mousewheel " + e.Delta + " ");
            if (e.Delta > 1 && mapslider.Value < mapslider.Maximum)
            {
                MapCanvas.FIELD_SIZE++;
               
            }
            if (e.Delta < 1 && mapslider.Value > mapslider.Minimum)
            {
                MapCanvas.FIELD_SIZE--;
            }
            // set slider, actual slider value and repaint
            mapslider.Value = MapCanvas.FIELD_SIZE;
            mapCanvas.InvalidateVisual();
        }

     
       private void hideChat(){
           bool windowVisible = (this.chatFeld.Visibility == System.Windows.Visibility.Visible);
           while(AUTO_CHAT_HIDE)
           {
               if (timeoutchat > 0)
               {
                   Dispatcher.BeginInvoke(new ThreadStart(() => this.chatFeld.Visibility = System.Windows.Visibility.Visible));
                   windowVisible = true;
                   timeoutchat--;
                   Thread.Sleep(1000);
               }
               else if(windowVisible)
               {
                   Console.WriteLine("collapse");
                   Dispatcher.BeginInvoke(new ThreadStart(() => this.chatFeld.Visibility = System.Windows.Visibility.Collapsed));
                   windowVisible = false;
               }
               else Thread.Sleep(1000); // frisst sonst zu viel cpu bei leerlauf
           }
       
       }

       private void mapScroll()
       {
           //double x = myPlayer.getX();
           //double y = myPlayer.getY();
           //double mx = backend.getMap().getWidth();
           //double my = backend.getMap().getHeigth();
           //double height = map.ScrollableHeight;
           //double width = map.ScrollableWidth;
           //map.ScrollToHorizontalOffset((height * (x / mx)));
           //map.ScrollToVerticalOffset((width * (y / my)));
        }


       private void findpath(MovementEnum[] path){
           Thread pathThread = new Thread(walkPath);
           this.movementPath = path;
           pathThread.Start();
       }
       private void walkPath()
       {
           if (movementPath == null)
           {
               MovementEnum[] path = { MovementEnum.UP, MovementEnum.RIGHT, MovementEnum.RIGHT, MovementEnum.DOWN, MovementEnum.RIGHT, MovementEnum.RIGHT, MovementEnum.UP };
               movementPath = path;
           }
           
           List<Point> pointPath = new List<Point>();
           int tempX = myPlayer.getX();
           int tempY = myPlayer.getY();
           int checkAttempt = 0;
           bool operationFailed = false;
           // create Point-Liste
           foreach (MovementEnum mov in movementPath)
           {
               switch (mov)
               {
                   case MovementEnum.UP: tempY--; break;
                   case MovementEnum.DOWN: tempY++; break;
                   case MovementEnum.RIGHT: tempX++; break;
                   case MovementEnum.LEFT: tempX--; break;
                   default: break;
               }
               pointPath.Add(new Point(tempX, tempY));
           }
           // mark Path
           foreach (Point p in pointPath)
           {
               mapCanvas.selection.Add(p);
           }

           // walk the path
           foreach (MovementEnum mov in movementPath)
           {
           // step 1: try to move
           mapCanvas.selection.Remove(pointPath[0]);
           if (!operationFailed)
           {
               backend.move(mov);
               // reset amount of check attempts
               checkAttempt = 0;
           } 
           // step 2: check if move was succsessful
           while (!(this.myPlayer.getX() == pointPath[0].X && this.myPlayer.getY() == pointPath[0].Y) && checkAttempt<5)
           {
               Thread.Sleep(500);
               checkAttempt++;
           }
            // if operation failed set flag
           if (checkAttempt >= 5)
               operationFailed = true;

           pointPath.RemoveAt(0);
           //--> back to step one
           }

           Dispatcher.BeginInvoke(new ThreadStart(() => mapCanvas.InvalidateVisual()));
       }
// end walkpath
       
       
       private void skirm_decision(object sender, RoutedEventArgs e)
       {
           if (!START_UP_MODE)
           {
               RadioButton s = (RadioButton)sender;
               ActionEnum action = ActionEnum.SWORD;
               switch (s.Content.ToString())
               {
                   case "Alchemy": action = ActionEnum.ALCHEMY; break;
                   case "Magic": action = ActionEnum.MAGIC; break;
                   case "Sword": action = ActionEnum.SWORD; break;
               }
               backend.challangeAction(action);
               Console.WriteLine(s.Content);
           }
       }

       private void dragon_decision(object sender, RoutedEventArgs e)
       {
           if (!START_UP_MODE)
           {
               RadioButton s = (RadioButton)sender;
               ActionEnum action = ActionEnum.SWORD;
               switch (s.Content.ToString())
               {
                   case "Fight": action = ActionEnum.FIGHT; break;
                   case "Rest": action = ActionEnum.REST; break;
               }
               backend.challangeAction(action);
               Console.WriteLine(s.Content);
           }
       }

       private void staghunt_decision(object sender, RoutedEventArgs e)
       {
           if (!START_UP_MODE)
           {
               RadioButton s = (RadioButton)sender;
               ActionEnum action = ActionEnum.SWORD;
               switch (s.Content.ToString())
               {
                   case "Stag": action = ActionEnum.STAG; break;
                   case "Bunny": action = ActionEnum.BUNNY; break;
               }
               backend.challangeAction(action);
               Console.WriteLine(s.Content);
           }
       }
      





      
    }
}
